package task3.combo;

import java.awt.image.renderable.ParameterBlock;
import java.io.StreamCorruptedException;
import javax.media.jai.JAI;
import task3.pimpmypipe.IOable;
import task3.pimpmypipe.Readable;
import task3.pimpmypipe.Writeable;
import task3.util.FilterObservable;
import task3.util.ImageTO;

public class ComboFilter
  implements IOable<ImageTO, ImageTO>, Runnable
{
  private Readable<ImageTO> _input1;
  private Readable<ImageTO> _input2;
  private Writeable<ImageTO> _output;
  private int _nextInput;
  private int _operation;
  private FilterObservable _observable;
  
  public ComboFilter()
  {
    this._nextInput = 0;
    this._operation = 0;
    this._observable = new FilterObservable();
  }
  
  public ImageTO read()
    throws StreamCorruptedException
  {
    return process((ImageTO)this._input1.read(), (ImageTO)this._input2.read());
  }
  
  public void write(ImageTO value)
    throws StreamCorruptedException
  {
    this._output.write(read());
  }
  
  public ImageTO process(ImageTO entity1, ImageTO entity2)
  {
    ParameterBlock parameter = new ParameterBlock();
    
    parameter.addSource(entity1.getEditedImage());
    parameter.addSource(entity2.getEditedImage());
    
    ImageTO image = new ImageTO();
    
    image.setSourceImage(entity1.getEditedImage());
    image.setFileName(entity1.getFileName());
    image.setRoiOffset(entity1.getRoiOffset());
    switch (this._operation)
    {
    case 0: 
      image.setEditedImage(JAI.create("and", parameter));
      break;
    case 1: 
      image.setEditedImage(JAI.create("or", parameter));
      break;
    case 2: 
      image.setEditedImage(JAI.create("xor", parameter));
    }
    this._observable.setChanged();
    this._observable.notifyObservers(image);
    
    return image;
  }
  
  public void setInput(Readable<ImageTO> input)
  {
    if (this._nextInput == 0)
    {
      this._input1 = input;
      this._nextInput = 1;
    }
    else if (this._nextInput == 1)
    {
      this._input2 = input;
      this._nextInput = 0;
    }
  }
  
  public void setOutput(Writeable<ImageTO> output)
  {
    this._output = output;
  }
  
  public void run()
  {
    try
    {
      write(read());
    }
    catch (StreamCorruptedException e)
    {
      e.printStackTrace();
    }
  }
  
  public int getOperation()
  {
    return this._operation;
  }
  
  public void setOperation(int operation)
  {
    this._operation = operation;
  }
  
  public FilterObservable getObservable()
  {
    return this._observable;
  }
}
